CloudFormationのパラメータでマルチバイト文字を入力する
ウィスキー、シガー、パイプをこよなく愛する大栗です。
CloudFormationで環境を構築することが多いのですが、EC2にミドルウェアを設定する時に環境固有の情報をパラメータから入力します。しかし日本語のようなマルチバイト文字を入力すると全て『?』と表示されてしまうので、環境を構築した後に個別に設定しており面倒でした。
最近CFnで日本語を入力する方法がわかったので紹介します。
ASCII文字に変換して入力する
結論として、マルチバイト文字を入力する方法はありませんでした。EC2のUserDataやMetadataへ流し込む時にマルチバイトが文字化けしてしまいます。
その代わり一旦ASCII文字に変換すれば、ASCII文字を入力することになるので使用できることがわかりました。CloudFormationで使用できる組み込み関数の中でASCII文字に変換できるのはFn::Base64です。Fn::Base64
を使用してBase64エンコーディングしてASCII文字として入力します。
具体的な記述方法
ダメな例
以下のようなCloudFormationテンプレートでEC2を1台起動して、入力したパラメータをファイルに出力しています。
CloudFormationテンプレートはYAML形式で記述しています。
AWSTemplateFormatVersion : 2010-09-09 Description : Linux Stack Parameters : TempVar1 : Type : String Default : PARAMETER TempVar2 : Type : String Default : PARAMETER KeyPairName : Type : String Default : KeyPairName Resources : Server01 : Type : AWS::EC2::Instance Properties : ImageId : ami-374db956 InstanceType : t2.small KeyName : !Ref KeyPairName UserData : Fn::Base64 : !Sub | #!/bin/bash /opt/aws/bin/cfn-init -s ${AWS::StackId} -r Server01 -c sample --region ${AWS::Region} Metadata : AWS::CloudFormation::Init : configSets : sample : - execute execute : files : /tmp/cfn-output.sh : content : !Sub | VAR1=${TempVar1} VAR2=${TempVar2} echo $VAR1 > /tmp/var1.txt echo $VAR2 >> /tmp/var1.txt mode : "000755" commands : a-write-output-file : command : /tmp/cfn-output.sh
以下のように入力します。
項目名 | 入力値 |
---|---|
KeyPairName | (各環境のキーペア) |
TempVar1 | クラスメソッド株式会社 |
TempVar2 | 大栗 |
起動したインスタンスの中身を確認します。
作成したスクリプトは以下のように文字化けしています。
$ cat /tmp/cfn-output.sh VAR1=??????????? VAR2=?? echo $VAR1 > /tmp/var1.txt echo $VAR2 >> /tmp/var1.txt
実行結果も当然文字化けしています。
$ cat /tmp/var1.txt ??????????? ??
修正した例
スクリプト部分を以下のように書き換えます。
!Sub
の第一引数にスクリプトの内容を記述します。ここで新しい変数である${MyVar1}
と${MyVar2}
を使用しています。base64 -d
でBase64デコードした結果をVAR1
とVAR2
に格納しています。
!Sub
の第二引数では、第一引数で使用した引数を定義します。MyVar1
はTempVar1
をBase64エンコードした内容、MyVar2
はTempVar1
をBase64エンコードした内容として定義します。
/tmp/cfn-output.sh : content : !Sub - | VAR1=$(echo ${MyVar1} | base64 -d) VAR2=$(echo ${MyVar2} | base64 -d) echo $VAR1 > /tmp/var1.txt echo $VAR2 >> /tmp/var1.txt - MyVar1: {"Fn::Base64": !Ref TempVar1} MyVar2: {"Fn::Base64": !Ref TempVar2}
このテンプレートを実行すると、スクリプトは以下になります。
$ cat /tmp/cfn-output.sh VAR1=$(echo 44Kv44Op44K544Oh44K944OD44OJ5qCq5byP5Lya56S+ | base64 -d) VAR2=$(echo 5aSn5qCX | base64 -d) echo $VAR1 > /tmp/var1.txt echo $VAR2 >> /tmp/var1.txt
出力結果では、日本語が表示できています。
$ cat /tmp/var1.txt クラスメソッド株式会社 大栗
さいごに
いかがでしょうか。Fn::Sub
を使ってスクリプト部分とCloudFormation側の変数定義が分離できるので、可読性が高いスッキリした記述となります。
CloudFormationのYAML対応を機にCloudFormationでインフラ環境のコード化を使用している方もいるようなので、参考になれば幸いです。